﻿using Microsoft.Practices.Unity;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.Linq.Expressions;
using System.Reactive.Concurrency;
using System.Reflection;
using System.Threading;
using System.Windows;
using Vroom.TableListener.Model;
using Vroom.TableListener.ViewModel;
using System.Reactive.Linq;
using System.Collections.Generic;
using System.Windows.Data;
using System.Windows.Controls;
using System.Windows.Media;

namespace Vroom.TableListener.Views
{

	public partial class MainView : Window, INotifyPropertyChanged
	{

		public event PropertyChangedEventHandler PropertyChanged;

		private ObservableCollection<DataSource> _tableRows;
		public ObservableCollection<DataSource> TableRows
		{
			get 
			{ return _tableRows; }
			set { _tableRows = value; OnPropertyChanged("TableRows"); }
		}

		#region Properties
		
		public MainViewModel MainViewModel { get; private set; } 

		#endregion


		public MainView([Dependency] MainViewModel mainViewModel)
		{
			InitializeComponent();
			MainViewModel = mainViewModel;
			DataContext = this;//MainViewModel;

			ConnectionStringtxt.Text = @"Data Source=HOST,PORT;Initial Catalog=DB_NAME;Integrated Security=True;";
			TableNameLblTxt.Text     = @"Sales.Customer";
			TableColsTxt.Text		 = @"3";

			TableRows = new ObservableCollection<DataSource>();

			

			dataGrid.ItemsSource = TableRows;
		}

		private void StartBtn_Click(object sender, RoutedEventArgs e)
		{

			TableRows.Clear();

			StopBtn.IsEnabled = true;
			StartBtn.IsEnabled = false;
			var stopClicked = Observable.FromEventPattern<EventArgs>(StopBtn, "Click");

			MainModel model = new MainModel(ConnectionStringtxt.Text);

			model.GetRows()
				 .ToObservable(NewThreadScheduler.Default)
				 .Buffer(10).TakeUntil(stopClicked)
				 .Throttle(TimeSpan.FromTicks(10))
				 .Timeout(TimeSpan.FromSeconds(3))				 
				 .ObserveOn(SynchronizationContext.Current)				 
				 .Subscribe
				 (
					 loadedData =>
						 {
							 int index = dataGrid.Items.IndexOf(dataGrid.CurrentItem);

							 foreach (DataSource ds in loadedData)
								TableRows.Add(ds);

							 if (dataGrid.Items.Count > 0)
							 {
								 var border = VisualTreeHelper.GetChild(dataGrid, 0) as Decorator;
								 if (border != null)
								 {
									 var scroll = border.Child as ScrollViewer;
									 if (scroll != null) scroll.ScrollToEnd();
								 }
							 }
						 },

					 exception => 
						{ Debug.Write(exception.Message);  StartBtn.IsEnabled=true; },

					 () => 
						{ Debug.WriteLine("Finished Loading Data"); StartBtn.IsEnabled = true; }
				 );

		}

		private void StopBtn_Click(object sender, RoutedEventArgs e)
		{

		}



		#region PropertyChanged Methods

		protected void OnPropertyChanged<T>(Expression<Func<T>> propertyExpresion)
		{
			var property = (MemberExpression)propertyExpresion.Body;
			VerifyPropertyExpression<T>(propertyExpresion, property);
			this.OnPropertyChanged(property.Member.Name);
		}


		protected void OnPropertyChanged(string propertyName)
		{
			if (this.PropertyChanged != null)
			{
				this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
			}
		}


		protected void SetValue<T>(ref T refValue, T newValue, Expression<Func<T>> propertyExpresion)
		{
			if (!object.Equals(refValue, newValue))
			{
				refValue = newValue;
				this.OnPropertyChanged(propertyExpresion);
			}
		}


		protected void SetValue<T>(ref T refValue, T newValue, Action valueChanged)
		{
			if (!object.Equals(refValue, newValue))
			{
				refValue = newValue;
				valueChanged();
			}
		}


		[Conditional("DEBUG")]
		private void VerifyPropertyExpression<T>(Expression<Func<T>> propertyExpresion, MemberExpression property)
		{
			if (property.Member.GetType().IsAssignableFrom(typeof(PropertyInfo)))
			{
				throw new ArgumentException(string.Format(
					CultureInfo.CurrentCulture,
					"Invalid Property Expression {0}",
					propertyExpresion));
			}

			var instance = property.Expression as ConstantExpression;
			if (instance.Value != this)
			{
				throw new ArgumentException(string.Format(
					CultureInfo.CurrentCulture,
					"Invalid Property Expression {0}",
					propertyExpresion));
			}
		} 

		#endregion

	}
}
